#ifndef USBCOMMUNICATION_H
#define USBCOMMUNICATION_H

#include <QObject>
#include <QThread>
#include "libusb.h"

class USBCommunication : public QThread
{
    Q_OBJECT
public:
    enum USB_Status{
        SUCCESS = 0,
        FAILED,
        TIMEOUT,
        HANDLE_IS_NONE,
        OTHER_ERROR,
        NOT_SUPPORT,
    };
public:
    explicit USBCommunication(QThread *parent = nullptr);
    ~USBCommunication();
    USB_Status usb_device_connect(void);
    USB_Status usb_device_disconnect(void);
    USB_Status usb_device_init(uint16_t vid,uint16_t pid, int _interface_number);
    USB_Status usb_device_start_hotplug(void);
    void usb_device_write_data(const QByteArray &data,unsigned char endpoint,unsigned int timeout = 0);
    USB_Status usb_device_start_receive(unsigned char endpoint);
    void usb_device_cancel_receive(void);

private:
    void run() override;
    USB_Status usb_device_transfer(unsigned char endpoint,unsigned char *buffer,size_t bytes,unsigned int timeout = 0);
    static int LIBUSB_CALL device_hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev, libusb_hotplug_event event, void *userdata);
    static void LIBUSB_CALL cbLibusbAsyncRead(libusb_transfer *transfer);
    static void LIBUSB_CALL cbLibusbAsyncSend(libusb_transfer *transfer);
    USB_Status usb_device_start_asynchronous_read(unsigned char endpoint);
    USB_Status usb_device_start_asynchronous_write(unsigned char endpoint,unsigned char *buff,size_t bytes);

private:
    struct usb_send_user
    {
        USBCommunication *handle;
    };
    libusb_context *ctx;
    libusb_device_handle *hUsbDevice;
    libusb_device *usb_device;
    int kernelDriverDetached;
    bool is_connect;
    uint16_t current_vid,current_pid;
    int interface_number;
    QByteArray receive_data;
    QList<libusb_transfer *> transfer_list;
    libusb_hotplug_callback_handle device_hotplug_handle;
    bool work;
    usb_send_user send_user;
    // unsigned char *write_buffer;

signals:
    void show_message(const QString &);
    void usb_device_receive_new_data(const QByteArray &data);
    void usb_device_send_finish(USB_Status status);
    void usb_device_is_connect(void);
    void usb_device_is_disconnect(void);
public slots:
    void usb_device_change(bool is_arrival,uint16_t vid,uint16_t pid,const QString &serial_number);

};

#endif // USBCOMMUNICATION_H
